package com.efounder.util;

import android.Manifest;
import android.annotation.SuppressLint;
import android.content.ContentResolver;
import android.content.ContentValues;
import android.content.Context;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.database.Cursor;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.net.Uri;
import android.net.wifi.WifiInfo;
import android.net.wifi.WifiManager;
import android.os.Build;
import android.os.Environment;
import android.provider.DocumentsContract;
import android.provider.MediaStore;
import android.provider.Settings;
import android.text.TextUtils;
import android.util.Log;
import android.webkit.MimeTypeMap;

import com.bun.miitmdid.core.Utils;
import com.efounder.constant.EnvironmentVariable;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Inet4Address;
import java.net.InetAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
import java.net.URI;
import java.util.Enumeration;
import java.util.UUID;

/**
 * 获取设备信息
 *
 * @author YQS
 */
public final class BaseDeviceUtils {
    private static final String TAG = "BaseDeviceUtils";
    private static final String DEVICE_ID_FILE_NAME = "OSPDevice.txt";


    public static String OSP_DEVICE_UNIQUE_KEY = "OSPDeviceId";
    public static String DEVICE_FILE_PATH = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getAbsolutePath();


    private BaseDeviceUtils() {
        throw new UnsupportedOperationException("u can't instantiate me...");
    }

    /**
     * Return whether device is rooted.
     *
     * @return {@code true}: yes<br>{@code false}: no
     */
    public static boolean isDeviceRooted() {
        String su = "su";
        String[] locations = {"/system/bin/", "/system/xbin/", "/sbin/", "/system/sd/xbin/",
                "/system/bin/failsafe/", "/data/local/xbin/", "/data/local/bin/", "/data/local/"};
        for (String location : locations) {
            if (new File(location + su).exists()) {
                return true;
            }
        }
        return false;
    }

    /**
     * Return the version name of device's system.
     * 获取系统版本字符串。如4.1.2 或2.2 或2.3等
     *
     * @return the version name of device's system
     */
    public static String getSDKVersionName() {
        return Build.VERSION.RELEASE;
    }

    /**
     * 获取设备品牌
     *
     * @return
     */
    public static String getDeviceBrand() {
        return Build.BRAND;
    }

    /**
     * 获取设备型号
     *
     * @return
     */
    public static String getDeviceModel() {
        return Build.MODEL;
    }


    /**
     * 是否支持移动安全联盟设备标识符获取
     *
     * @return
     */
    public static boolean supportMittDeviceId() {
        //这里我们判断一下，如果支持移动安全联盟设备标识符i获取，那我们就不在请求READ_PHONE_STATE权限，因为此权限获取敏感
        //支持唯一id获取并且oaid不是空
        if (EnvironmentVariable.getProperty("supportMiit", "").equals("1") && !TextUtils.isEmpty(EnvironmentVariable.getProperty("miitOAID", ""))) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * 获取设备唯一id
     * 参考 https://blog.csdn.net/sunsteam/article/details/73189268
     *
     * @param context
     * @return
     */
    public static String getUniqueId(Context context) {
        String deviceId = null;

        File file = new File(DEVICE_FILE_PATH, "OSPDevice.txt");
//        if (file.exists()) {
//            try {
//                deviceId = ESPFileIOUtils.readFile2String(file);
//            } catch (Exception e) {
//                e.printStackTrace();
//                file.delete();
//            }
//        }

        try {
            Uri deviceFileUri = getFileContentUriByResolver(DEVICE_FILE_PATH + "/" + DEVICE_ID_FILE_NAME);
            if (deviceFileUri != null) {
                FileInputStream fileInputStream = (FileInputStream) AppContext.getInstance().getContentResolver().openInputStream(deviceFileUri);
                deviceId = ESPFileIOUtils.readFileInputStream2String(fileInputStream, null);
                Log.e(TAG, "OSPDevice.txt读取到的deviceId=" + deviceId);
            }
        } catch (Exception e) {
            e.printStackTrace();
            Log.e(TAG, "OSPDevice.txt读取deviceid失败");

        }


        //从文件中读取成功
        if (!TextUtils.isEmpty(deviceId)) {
            return deviceId;
        }
        //文件中没有存储,首先尝试读取广告联盟的OAID
        String envOAID = EnvironmentVariable.getProperty("miitOAID", "");
        if (!TextUtils.isEmpty(envOAID)) {
            deviceId = envOAID;
        } else {
            String androidID = Settings.Secure.getString(context.getContentResolver(), Settings.Secure.ANDROID_ID);
            String serial = null;
            // Android 9 中，调用Build.SERIAL 会始终返回 UNKNOWN 以保护用户的隐私。如果你的应用需要访问设备的硬件序列号，
            // 那么需要先请求 READ_PHONE_STATE 权限，然后调用 Build.getSerial()。
            if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
                try {
                    if (AppContext.getInstance().checkSelfPermission(Manifest.permission.READ_PHONE_STATE) != PackageManager.PERMISSION_GRANTED) {
                        serial = Build.getSerial();
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            } else {
                serial = Build.SERIAL;
            }
            if (TextUtils.isEmpty(serial) || "unknown".equals(serial.toLowerCase())) {
                if (!TextUtils.isEmpty(EnvironmentVariable.getProperty("OSPDeviceSerial", ""))) {
                    serial = EnvironmentVariable.getProperty("OSPDeviceSerial", "");
                } else {
                    serial = UUID.randomUUID().toString().substring(20).replace("-", "");
                }
                EnvironmentVariable.setProperty("OSPDeviceSerial", serial);
            }
            deviceId = androidID + serial;
        }


        //存入文件 androidq以后放弃保存因为无法写入到文件
        if (android.os.Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q
                && AppContext.getInstance().getApplicationInfo().targetSdkVersion >= Build.VERSION_CODES.Q) {
            //直接返回，不往下执行保存文件
            return deviceId;
        }


//            try {
//                Uri fileUri = MediaStore.Files.getContentUri("external");
//                if (writeTextToFile(deviceId, DEVICE_ID_FILE_NAME, fileUri)) {
//                    Log.e(TAG, "deviceId写入文件成功");
//                }
//            } catch (Exception e) {
//                e.printStackTrace();
//                Log.e(TAG, "deviceId写入文件失败");
//
//            }


        if (file != null && !file.getParentFile().exists()) {
            file.getParentFile().mkdirs();
        }
        try {
            InputStream inputStream = new ByteArrayInputStream(deviceId.getBytes());
            ESPFileIOUtils.writeFileFromIS(file, inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return deviceId;
    }

    /**
     * 从文件路径获取Uri
     *
     * @param path
     * @return
     */
    private static Uri getFileContentUriByResolver(String path) {
        Cursor cursor = AppContext.getInstance().getContentResolver().query(MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL),
                new String[]{MediaStore.Files.FileColumns._ID}, MediaStore.Files.FileColumns.DATA + "=? ",
                new String[]{path}, null);
        if (cursor != null && cursor.moveToFirst()) {
            int id = cursor.getInt(cursor.getColumnIndex(MediaStore.MediaColumns._ID));
            //Uri.parse("content://media/external/images/media") 两种方式是一样的
            Uri baseUri = MediaStore.Files.getContentUri(MediaStore.VOLUME_EXTERNAL);
            return Uri.withAppendedPath(baseUri, "" + id);
        } else {
            return null;
        }
    }

    /**
     * 通过uri的方式将文本写入到文件
     *
     * @param text
     * @param displayName
     * @param externalUri
     * @return
     */
    public static boolean writeTextToFile(String text, String displayName, Uri externalUri) {
        ContentValues values = new ContentValues();
        values.put(MediaStore.Files.FileColumns.DISPLAY_NAME, displayName);
        values.put(MediaStore.Files.FileColumns.MIME_TYPE, getMimeType(displayName));
        values.put(MediaStore.Files.FileColumns.TITLE, displayName);
//        if (relativePath != null && Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
//            //公共目录下目录名
//            values.put(MediaStore.Files.FileColumns.RELATIVE_PATH, relativePath);
//        }

//        Uri external = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;//外部存储的Download路径
        ContentResolver resolver = AppContext.getInstance().getContentResolver();
        Uri insertUri = resolver.insert(externalUri, values);
        if (insertUri == null) {
            return false;
        }
        String mFilePath = insertUri.toString();
        Log.i(TAG, "存储文件路径为" + mFilePath);
        InputStream is = null;
        OutputStream os = null;
        try {
            os = resolver.openOutputStream(insertUri);
            if (os == null) {
                return false;
            }
            int read;


            is = new ByteArrayInputStream(text.getBytes());
            byte[] buffer = new byte[1024];
            while ((read = is.read(buffer)) != -1) {
                os.write(buffer, 0, read);
            }
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        } finally {
            CloseUtils.closeIO(is);
            CloseUtils.closeIO(os);
        }
        return true;
    }

    public static String getMimeType(String filePath) {
        String ext = MimeTypeMap.getFileExtensionFromUrl(filePath);
        return MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext);
    }

    /**
     * 获取ip
     *
     * @param context
     * @return
     */
    public static String getIPAddress(Context context) {
        try {
            NetworkInfo info = ((ConnectivityManager) context
                    .getSystemService(Context.CONNECTIVITY_SERVICE)).getActiveNetworkInfo();
            if (info != null && info.isConnected()) {
                if (info.getType() == ConnectivityManager.TYPE_MOBILE) {//当前使用2G/3G/4G网络
                    try {
                        //Enumeration<NetworkInterface> en=NetworkInterface.getNetworkInterfaces();
                        for (Enumeration<NetworkInterface> en = NetworkInterface.getNetworkInterfaces(); en.hasMoreElements(); ) {
                            NetworkInterface intf = en.nextElement();
                            for (Enumeration<InetAddress> enumIpAddr = intf.getInetAddresses(); enumIpAddr.hasMoreElements(); ) {
                                InetAddress inetAddress = enumIpAddr.nextElement();
                                if (!inetAddress.isLoopbackAddress() && inetAddress instanceof Inet4Address) {
                                    return inetAddress.getHostAddress();
                                }
                            }
                        }
                    } catch (SocketException e) {
                        e.printStackTrace();
                    }

                } else if (info.getType() == ConnectivityManager.TYPE_WIFI) {//当前使用无线网络
                    WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
                    WifiInfo wifiInfo = wifiManager.getConnectionInfo();
                    String ipAddress = intIP2StringIP(wifiInfo.getIpAddress());//得到IPV4地址
                    return ipAddress;
                }
            } else {
                //当前无网络连接,请在设置中打开网络
            }
            return null;
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }


    /**
     * 获取app名称
     *
     * @return
     */
    public static String getAppName() {

        try {
            PackageManager pm = AppContext.getInstance().getPackageManager();
            PackageInfo pi = pm.getPackageInfo(AppContext.getInstance().getPackageName(), 0);
            return pi == null ? null : pi.applicationInfo.loadLabel(pm).toString();
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 获取app版本号
     *
     * @return
     */
    public static String getAppVersion() {

        try {
            PackageManager pm = AppContext.getInstance().getPackageManager();
            PackageInfo pi = pm.getPackageInfo(AppContext.getInstance().getPackageName(), 0);
            return pi == null ? null : pi.versionName;
        } catch (PackageManager.NameNotFoundException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 将得到的int类型的IP转换为String类型
     *
     * @param ip
     * @return
     */
    public static String intIP2StringIP(int ip) {
        return (ip & 0xFF) + "." +
                ((ip >> 8) & 0xFF) + "." +
                ((ip >> 16) & 0xFF) + "." +
                (ip >> 24 & 0xFF);
    }

    /**
     * Return version code of device's system.
     *
     * @return version code of device's system
     */
    public static int getSDKVersionCode() {
        return Build.VERSION.SDK_INT;
    }

    /**
     * Return the android id of device.
     *
     * @return the android id of device
     */
    @SuppressLint("HardwareIds")
    public static String getAndroidID() {
        return Settings.Secure.getString(
                AppContext.getInstance().getContentResolver(),
                Settings.Secure.ANDROID_ID
        );
    }


    @SuppressLint({"HardwareIds", "MissingPermission"})
    private static String getMacAddressByWifiInfo() {
        try {
            Context context = AppContext.getInstance();
            WifiManager wifi = (WifiManager) context.getApplicationContext().getSystemService(Context.WIFI_SERVICE);
            if (wifi != null) {
                WifiInfo info = wifi.getConnectionInfo();
                if (info == null) {
                } else {
                    return info.getMacAddress();
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "02:00:00:00:00:00";
    }

    private static String getMacAddressByNetworkInterface() {
        try {
            Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
            while (nis.hasMoreElements()) {
                NetworkInterface ni = nis.nextElement();
                if (ni != null && ni.getName().equalsIgnoreCase("wlan0")) {
                    byte[] macBytes = ni.getHardwareAddress();
                    if (macBytes != null && macBytes.length > 0) {
                        StringBuilder sb = new StringBuilder();
                        for (byte b : macBytes) {
                            sb.append(String.format("%02x:", b));
                        }
                        return sb.substring(0, sb.length() - 1);
                    }
                } else {
                    continue;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "02:00:00:00:00:00";
    }

    private static String getMacAddressByInetAddress() {
        try {
            InetAddress inetAddress = getInetAddress();
            if (inetAddress != null) {
                NetworkInterface ni = NetworkInterface.getByInetAddress(inetAddress);
                if (ni != null) {
                    byte[] macBytes = ni.getHardwareAddress();
                    if (macBytes != null && macBytes.length > 0) {
                        StringBuilder sb = new StringBuilder();
                        for (byte b : macBytes) {
                            sb.append(String.format("%02x:", b));
                        }
                        return sb.substring(0, sb.length() - 1);
                    }
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "02:00:00:00:00:00";
    }

    private static InetAddress getInetAddress() {
        try {
            Enumeration<NetworkInterface> nis = NetworkInterface.getNetworkInterfaces();
            while (nis.hasMoreElements()) {
                NetworkInterface ni = nis.nextElement();
                // To prevent phone of xiaomi return "10.0.2.15"
                if (ni.isUp()) {
                    Enumeration<InetAddress> addresses = ni.getInetAddresses();
                    while (addresses.hasMoreElements()) {
                        InetAddress inetAddress = addresses.nextElement();
                        if (!inetAddress.isLoopbackAddress()) {
                            String hostAddress = inetAddress.getHostAddress();
                            if (hostAddress.indexOf(':') < 0) {
                                return inetAddress;
                            }
                        }
                    }
                }
            }
        } catch (SocketException e) {
            e.printStackTrace();
        }
        return null;
    }


    /**
     * Return the manufacturer of the product/hardware.
     * <p>e.g. Xiaomi</p>
     *
     * @return the manufacturer of the product/hardware
     */
    public static String getManufacturer() {
        return Build.MANUFACTURER;
    }

    /**
     * Return the model of device.
     * <p>e.g. MI2SC</p>
     *
     * @return the model of device
     */
    public static String getModel() {
        String model = Build.MODEL;
        if (model != null) {
            model = model.trim().replaceAll("\\s*", "");
        } else {
            model = "";
        }
        return model;
    }

    /**
     * Return an ordered list of ABIs supported by this device. The most preferred ABI is the first
     * element in the list.
     *
     * @return an ordered list of ABIs supported by this device
     */
    public static String[] getABIs() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            return Build.SUPPORTED_ABIS;
        } else {
            if (!TextUtils.isEmpty(Build.CPU_ABI2)) {
                return new String[]{Build.CPU_ABI, Build.CPU_ABI2};
            }
            return new String[]{Build.CPU_ABI};
        }
    }


}
